package com.boot2.core.web.filter;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.boot2.core.constant.HttpConstant;
import com.boot2.core.dict.ErrorCode;
import com.boot2.core.model.vo.Result;
import com.boot2.core.utils.Base64SerializeUtils;
import com.boot2.core.utils.JwtUtil;
import com.boot2.core.utils.ResultBuilder;
import com.boot2.core.utils.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * @author zhangweilin
 * @description: 多种方式登录, 如本地用户，google ,facebook,等
 * @date 2018/9/30
 */
//@Component
//public abstract class MultipleJwtAuthenticationFilter extends JwtAuthenticationFilter {
public abstract class MultipleJwtAuthenticationFilter extends OncePerRequestFilter {

    /**
     * 登录map里的键值
     */
    public static final String CHANNEL_KEY = "channel";

    /**
     * 登录map里的键值
     */
    public static final String USER_ID = "userId";

    public MultipleJwtAuthenticationFilter() {

    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        String key = JwtAuthenticationFilter.class.getName() + ALREADY_FILTERED_SUFFIX;
        boolean alreadyFilteredBaseJwt = request.getAttribute(key) != null;
        request.removeAttribute(key);
        //只有进行过基础认证，才进行下一步认证
        if (!alreadyFilteredBaseJwt) {
            return true;
        }
        return false;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        boolean committed = response.isCommitted();
        //如果已经提前过，说明在前一步就已经返回了错误信息了，不必再往下校验
        if (committed) {
            return;
        }
        boolean isNeedToken = true;
        Object isNeedTokenObj = request.getAttribute(JwtAuthenticationFilter.class.getName() + JwtAuthenticationFilter.isNeedToken);
        if (isNeedTokenObj != null) {
            isNeedToken = (boolean) isNeedTokenObj;
        }
        String base64 = request.getHeader(JwtUtil.USER_ID);
        //当header里为空时
        if (StringUtils.isEmpty(base64)) {
            //如果标记是是要登录的，则校验拦截
            if (isNeedToken) {
                notLogined(response, "  token is invalid,can not get user info ");
            }else{
                //不需要登录的话，直接返回即可
//                filterChain.doFilter(request, response);
                super.doFilter(request, response,filterChain);
                return;
            }
        }
        Object object = null;
        try {
            object = Base64SerializeUtils.deserializeFromString(base64);
        } catch (Exception e) {
            e.printStackTrace();
            notLogined(response, e.getMessage() + ", token is invalid ");
            return;
        }
        if (object instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) object;
            Object valueObject = map.get(CHANNEL_KEY);
            if (null == valueObject) {
                notLogined(response, "token is invalid ");
                return;
            }

            Object userId = map.get(USER_ID);
            if (null == userId) {
                notLogined(response, "user id is invalid ");
                return;
            }
            //按正常的渠道登录成功
            handLogin(map, request, response, filterChain);
        } else {
            notLogined(response, "token is invalid ");
            return;
        }
//        filterChain.doFilter(request, response);
//        super.doFilter(request, response,filterChain);
    }

    /**
     * 处理多渠道登录
     *
     * @param map
     * @param request
     * @param response
     */
    public abstract void handLogin(Map<String, Object> map, HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException;

    private void notLogined(HttpServletResponse response, String s) throws IOException {
        Result<String> result0 = ResultBuilder.buildResult(ErrorCode.code_403, s);
        String json = JSONObject.toJSONString(result0, SerializerFeature.WriteDateUseDateFormat);
        response.setContentType(HttpConstant.contentTypeJsonUTF8);
        response.getWriter().write(json);
        return;
    }

    /**
     * 登录渠道
     */
    public static enum LoginChannel {
        base, wechat, alipay, google, facebook, twitter, linkedin;
    }
}
